#include "stdafx.h"

#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/util/XMLString.hpp> 
#include <xercesc/util/OutOfMemoryException.hpp> 
#include <xercesc/util/TransService.hpp>
#include <xercesc/parsers/XercesDOMParser.hpp>
#include <xercesc/util/XMLUni.hpp>
#include <xercesc/framework/MemBufFormatTarget.hpp>
#include <xercesc/framework/MemBufInputSource.hpp>
#include <xercesc/framework/Wrapper4InputSource.hpp>
#include <xercesc/parsers/AbstractDOMParser.hpp>

#include <locale.h>

using namespace xml;
static PXmlLibInit __gp_Xerces_init;

static class xerces_initializer
{
public:
	xerces_initializer() { __gp_Xerces_init.reset(new XmlLibInit()); }
} __xerc_init;

XmlLibInit::XmlLibInit()
{
	setlocale(LC_ALL,"");
	XMLPlatformUtils::Initialize();
}

XmlLibInit::~XmlLibInit()
{
	XMLPlatformUtils::Terminate();
}

const data_type		pnode::int_type(		"int"		);
const data_type		pnode::string_type(		"string"	);
const data_type		pnode::boolean_type(	"boolean"	);
const data_type		pnode::float_type(		"float"		);
const data_type		pnode::ui4_type(		"ui4"		);
const data_type		pnode::datetime_type(	"dateTime"	);
const attribute		pnode::typeid_attribute("typeid"	);
const attribute		pnode::msdt_attribute(	"dt:dt"		);
const attribute		pnode::size_attribute(	"size"		);
const attribute		pnode::index_attribute(	"index"		);
const element		pnode::item_element(	"item"		);
const std::string	pnode::array_type(		"array"		);
const std::string	pnode::empty_string(	""			);

pnode pnode::clone( bool deep ) const
{
	return _node_ptr->cloneNode( deep );
}

pnode pnode::operator <<( const xml::element& i )
{		
	IXMLDOMElementPtr eptr;
	eptr = _node_ptr->getOwnerDocument()->createElement( X(i.name.c_str()) );
	_node_ptr->appendChild( eptr );
	return eptr;
}

pnode pnode::operator <<( const xml::attribute& i )
{
	IXMLDOMAttributePtr	aptr;
	aptr = _node_ptr->getOwnerDocument()->createAttribute( X(i.name.c_str()) );
	_node_ptr->getAttributes()->setNamedItem( aptr );
	return aptr;
}

pnode& pnode::operator <<( const pconstxmlobject& i )
{
	*this << typeid_attribute << i->xml_get_typeid();
	i->xml_save_state( *this );
	return *this;
}

pnode& pnode::operator <<( const xml::pnode& i )
{
	_node_ptr->appendChild( i.clone().get_node_ptr() );
	return *this;
}

pnode& pnode::operator <<( const std::map<std::string,hc::_value_t>& i )
{
	for( std::map<std::string,hc::_value_t>::const_iterator ci = i.begin(); ci != i.end(); ++ci )
		*this << xml::element(ci->first) << (const hc::_value_t&)ci->second;
	return *this;
}

const std::string& get_msdt(const hc::_value_t& v)
{
#define MAP_TYPE(T,EL_TYPE)	if(const T* p=boost::any_cast< T >(&v)) return pnode::EL_TYPE##_type.type;
	
	MAP_TYPE(int,int)
	MAP_TYPE(unsigned long,ui4)
	MAP_TYPE(bool,boolean)
	if(const std::string* p=boost::any_cast< std::string >(&v)) return pnode::string_type.type;
	if(const std::wstring* p=boost::any_cast< std::wstring >(&v)) return pnode::string_type.type;
	if(const std::list<std::string>* p=boost::any_cast< std::list<std::string> >(&v)) return pnode::array_type;	
		
	throw hc::CException(hc::ex_val("Can't map _value_t native type on pnode::msdt",std::string(v.type().name())));
}

template<class T> pnode& pnode::operator <<( const std::list<T>& i )
{
	// only element nodes!
	if(_node_ptr->getNodeType() != xercesc::DOMNode::ELEMENT_NODE)
		throw hc::CException(hc::ex_val("Operation <<list is not supported for non-element node",get_name()));
	
	*this << typeid_attribute << array_type;
	*this << size_attribute << (unsigned long)i.size();

	typename std::list<T>::const_iterator li_beg = i.begin(), li;
	for( li = i.begin(); li!= i.end(); li++)
	{
		///*typename list<T>::difference_type*/int n = 0; n < i.size(); ++n ) 
		//*this << item_element << *(n+li) << index_attribute << (unsigned long)n;
		*this << item_element << *li << index_attribute << (unsigned long)distance(li_beg,li);
	}
	return *this;
}


pnode& pnode::operator <<( const hc::_value_t& i ) 
{ 
	if(_node_ptr->getNodeType() == xercesc::DOMNode::ELEMENT_NODE)
	{
		const std::string& _msdt = get_msdt(i);
		
		if(_msdt == array_type)
		{
			*this << boost::any_cast< std::list<std::string> >(i);
		}
		else
		{
			*this << msdt_attribute << _msdt;
			*this << pnode(_node_ptr->getOwnerDocument()->createTextNode( X(hc::as_string(i).c_str())));
		}
	}
	else // only attributes seem to appear here?
	{
		_node_ptr->setNodeValue( X(hc::as_string(i).c_str()) );
	}
	return *this; 
}

const pnode& pnode::operator >>( hc::_value_t& o ) const
{ 
	if(!_node_ptr) return *this;

	if(_node_ptr->getNodeType() == xercesc::DOMNode::ELEMENT_NODE)
	{
		pnode pAttr;

		// try if complex value
		pAttr = (*this) >> typeid_attribute;
		if( (*this>>msdt_attribute).valid() )
		{
			std::string dt_name;
			*this >> pnode::msdt_attribute >> dt_name;
			pnode subnode = (*this >> xml::node());
			if(!subnode.valid()) return *this;
			
			if(dt_name == pnode::string_type.type) 			o = subnode.as_string();
			else if(dt_name == pnode::int_type.type)	 	o = subnode.as_int();
			else if(dt_name == pnode::ui4_type.type)	 	o = subnode.as_ulong();
			else if(dt_name == pnode::boolean_type.type)	o = subnode.as_bool();
			else if(dt_name == pnode::array_type)				as_list(o);
			else 
				throw hc::CException(std::pair<std::string,hc::_value_t>("Unknown dt_name",dt_name));
		}
		else
			throw hc::CException(std::pair<std::string,hc::_value_t>("Unknown type attribute in node",get_name()));
	}
	else
	{
		o = this->as_string();
	}
	return *this; 
}

const pnode pnode::operator >>( const xml::attribute& i ) const
{
	if(!_node_ptr) return NULL;

	IXMLDOMNamedNodeMapPtr	attributes = _node_ptr->getAttributes();

	if( attributes == NULL )
		return NULL;
	return attributes->getNamedItem( X(i.name.c_str()) );
}
	

bool pnode::exist_value_in_node(const std::string& i) const
{
	pnode p=(*this)>>xml::node(i);
	if(!p.valid()) return false;

	return (p>>xml::node()).valid();
}

const pnode pnode::operator >>( const xml::node& i ) const
{
	if(!_node_ptr) return NULL;
	
	if(i.name.empty()) // try to get text subnode (typed value)
	{
		return _node_ptr->getFirstChild();
		
		//if(!np) 
		//	throw CException(	ex_val("No children",string()),
		//						ex_val("Root node",get_name()));
		//else
		//	return np;
	}	
	
	IXMLDOMNodeListPtr child_nodes = _node_ptr->getChildNodes();
	XMLSize_t child_quant = child_nodes->getLength();
	for(XMLSize_t i_child = 0;i_child!=child_quant;i_child++)
	{
		IXMLDOMNodePtr p_node = child_nodes->item(i_child);
		if(XMLString::equals(p_node->getNodeName(),X(i.name.c_str())))
			return p_node;
	}
	
	return NULL;
	//throw CException(	ex_val("No such subnode",i.name),
	//				ex_val("Root node",get_name()));
}

const pnodelist pnode::operator >>( const xml::nodelist& o ) const
{
	return pnodelist(this->_node_ptr, o.name);	
}

pnodelist		pnode::get_children() const
{
	return pnodelist(_node_ptr, "*" );	
}

namespace
{
	class nodeSearcher
	{
	public:
		nodeSearcher(IXMLDOMNodePtr iptr):m_ptrNode(iptr)
		{}
		list<IXMLDOMNodePtr> Run(const string& path)
		{
			try
			{
				if ( path[0] == '/' && path[1] == '/')
				{
					m_path.assign (path.begin()+2, path.end() );
					SearchByDoc();
				}
				else if (path[0] == '/')
				{
					m_path.assign( path.begin()+1, path.end() );
					SearchFromRoot();
				}
				else if (path == "*")
				{
					GetChildrenNodes();
				}
				else
					SearchNode();
			}
			catch (exception& e)
			{}
			return m_nodes;
		}

		list<IXMLDOMNodePtr> GetResult()
		{
			return m_nodes;
		}
	private:
		void SearchFromRoot() 
		{
			m_ptrNode = m_ptrNode->getOwnerDocument()->getDocumentElement();

			typedef boost::tokenizer< boost::char_separator<char> > tokenizer;
			boost::char_separator<char> sep("/");
			tokenizer tokens(m_path, sep);
			tokenizer::iterator tok_iter = tokens.begin();
			
			if ( !CompareNodeName(m_ptrNode, (*tok_iter)) )
				throw hc::CException( pair<string,string>("Simple XPath Exception","Start node not match with input value"), pair<string, string>("Value", X2C(m_ptrNode->getNodeValue()) ) );
			++tok_iter;
			for (; tok_iter != tokens.end(); ++tok_iter)
			{
				m_ptrNode = Search( *tok_iter);
			}
			m_ptrNode = m_ptrNode->getParentNode();
			MakeFeedback();
		}
		void SearchByDoc()
		{}
		void SearchNode()
		{}
		void GetChildrenNodes()
		{
			m_lastNodeName = "*";
			MakeFeedback();
		}

		IXMLDOMNodePtr Search( const string& nodeName)
		{
			IXMLDOMNodeListPtr nodes = m_ptrNode->getChildNodes();
			for ( XMLSize_t i= 0; i < nodes->getLength(); ++i)
			{
				if (  nodeName == "*" || CompareNodeName( nodes->item(i), nodeName ) )
				{
					m_lastNodeName = nodeName;
					return nodes->item(i);
				}
			}
			throw hc::CException(hc::ex_val("Cant`t find node", nodeName) );
		}
		
		bool CompareNodeName(const IXMLDOMNodePtr node, const string& name)
		{
			return ( X2C(node->getNodeName()) == name );
		}
		void MakeFeedback()
		{
			IXMLDOMNodeListPtr nodes = m_ptrNode->getChildNodes();
			for ( XMLSize_t i= 0; i < nodes->getLength(); ++i)
			{
				if ( m_lastNodeName == "*" || CompareNodeName( nodes->item(i), m_lastNodeName ) )
				{
					if ( nodes->item(i)->getNodeType() == xercesc::DOMNode::ELEMENT_NODE )
						m_nodes.push_back( nodes->item(i) );
				}
			}
		}

		list< IXMLDOMNodePtr > m_nodes;
		string m_path;
		string m_lastNodeName;
		IXMLDOMNodePtr m_ptrNode;
	};

	list<IXMLDOMNodePtr> make(IXMLDOMNodePtr iptr, const string& iname )
	{
		nodeSearcher _searcher(iptr);
		_searcher.Run(iname);
		return _searcher.GetResult();
	}
}

pnodelist::pnodelist( IXMLDOMNodePtr iptr, const string& iname )
	: _node_ptr(iptr), _nodes_ptr( make(iptr, iname) ), _nodes_itr (_nodes_ptr.begin() )
{}

pnodelist::pnodelist( const pnodelist& nodelist)
{
	_node_ptr = nodelist._node_ptr;
	_nodes_ptr = nodelist._nodes_ptr;
	_nodes_itr = _nodes_ptr.begin();
}

long pnodelist::length() const
{
	return _nodes_ptr.size();
}

bool pnodelist::have_next() const 
{
	list<IXMLDOMNodePtr>::const_iterator _itr = _nodes_itr;
	if (_itr == _nodes_ptr.end() || ++_itr == _nodes_ptr.end() )
		return false;
	return true;
}

pnode pnodelist::nextnode() const
{
	IXMLDOMNodePtr tmp_nodes_ptr;
	if ( _nodes_itr != _nodes_ptr.end() )
		tmp_nodes_ptr = (*_nodes_itr);
	else
		tmp_nodes_ptr = NULL;

	if ( have_next() )
	{
		//++( (const_cast<pnodelist*>(this))->_nodes_itr );
		++_nodes_itr;
	}
	else
	{
		//( (const_cast<pnodelist*>(this))->_nodes_itr ) = _nodes_ptr.end();
		_nodes_itr = _nodes_ptr.end();
	}

	
	pnode _node( tmp_nodes_ptr );
	return _node;
}

const pnode& pnode::operator >>( std::map<std::string,hc::_value_t>& o ) const
{
	IXMLDOMNodeListPtr child_nodes = _node_ptr->getChildNodes();
	XMLSize_t child_quant = child_nodes->getLength();
	for(XMLSize_t i_child = 0;i_child!=child_quant;i_child++)
	{
		pnode node_(child_nodes->item(i_child));
		hc::_value_t dt_val;
		node_ >> dt_val;
		o[node_.get_name()]=dt_val;
	}	
	return *this;
}

std::string			pnode::get_name()	const 
{ 
	return X2C(_node_ptr->getNodeName()); 
}

std::string			pnode::as_string() 	const 
{ 
	if(_node_ptr->getNodeValue())
		return X2C(_node_ptr->getNodeValue()); 
	else
	{
		if(_node_ptr->getNodeType() == xercesc::DOMNode::ELEMENT_NODE)
		{
			pnode p = (*this)>>xml::node();
			if(p.valid())
			{
				if ( p.get_node_ptr()->getNodeType() == xercesc::DOMNode::TEXT_NODE )
					return p.as_string();
			}
		}
	}
	throw hc::CException( hc::ex_val("Empty value in node",get_name()), hc::ex_val("Unable to get string",std::string()) );
}

std::wstring 		pnode::as_wstring() const 
{ 
	return hc::as_wstring(this->as_string()); 
}

int pnode::as_int() 	const 
{
	try 
	{
		return XMLString::parseInt(_node_ptr->getNodeValue());
	}
    catch (const XMLException& toCatch) 
	{ 
		throw hc::CException(	hc::ex_val("XMLException",std::string(X2C(toCatch.getMessage()))), hc::ex_val("Value",as_string())); 
	}
    catch (const DOMException& toCatch) 
	{ 
		throw hc::CException(	hc::ex_val("DOMException",std::string(X2C(toCatch.msg))), hc::ex_val("Value",as_string())); 
	}
}

template<class T> 
void extract_list(pnode i_lst_root,hc::_value_t& o_val)
{
	std::list<T> lst_;
	T t;
	pnodelist nodes = i_lst_root >> xml::nodelist(pnode::item_element.name) ;
	while(nodes.have_next())
	{
		pnode list_item_ = nodes.nextnode();

		list_item_ >> t;
		lst_.push_back(t);
	}

	o_val = lst_;
}

void 	pnode::as_list(hc::_value_t& o_val) const
{
	unsigned long list_size_ = 0;
	*this >> size_attribute >> list_size_;

	pnodelist nodes = *this >> xml::nodelist(item_element.name) ;
	if(nodes.have_next())
	{
		std::string dt_name;
		pnode first_ = nodes.nextnode();
	   	first_ >> pnode::msdt_attribute >> dt_name;
	
		if(dt_name == pnode::string_type.type) 
		{ 
			extract_list<std::string>(*this,o_val); 
		}
		else if(dt_name == pnode::int_type.type) 
		{ 
			extract_list<int>(*this,o_val); 
		}
		else 
			throw hc::CException(	hc::ex_val("Type",dt_name), hc::ex_val("Not supported for list output",get_name()));
	}	
}

unsigned long 	pnode::as_ulong() 	const { return (unsigned long)as_int(); }
bool 			pnode::as_bool() 	const { return as_int()==1; }

template<> std::wstring pnode::get<std::wstring>() const {return as_wstring();}
template<> std::string pnode::get<std::string>() const {return as_string();}
template<> int pnode::get<int>() const {return as_int();}
template<> unsigned long pnode::get<unsigned long>() const {return as_ulong();}
template<> bool pnode::get<bool>() const {return as_bool();}

pattribute::pattribute( IXMLDOMAttributePtr iptr ) :_attribute_ptr( iptr )
{_node_ptr = _attribute_ptr;}

pelement::pelement( IXMLDOMElementPtr iptr )
:_element_ptr( iptr )
{
	_node_ptr = _element_ptr;
}

pdocument::pdocument()
: _document_ptr(NULL)
, _doc_allocated(false)
, _dom_builder(NULL)
{
	//cout << __FUNCTION__ << ": xerces_use=" << __gp_Xerces_init.use_count() << endl;
}

pdocument::pdocument(const std::string& iFile)
: _document_ptr(NULL)
, _doc_allocated(false)
, _dom_builder(NULL)
{
	//cout << __FUNCTION__ << ": xerces_use=" << __gp_Xerces_init.use_count() << endl;
	load_xml(iFile);
}

pdocument::~pdocument()
{
	//cout << "(!!!) ~pdocument :" << _docid << endl;
	//cout << "~" << __FUNCTION__ << ": xerces_use=" << __gp_Xerces_init.use_count() << endl;

	if(_dom_builder)
	{
		_dom_builder->release();
		_dom_builder = NULL;
	}

	if(_doc_allocated && _document_ptr)
	{
		_document_ptr->release();
		_document_ptr = NULL;
	}
}

pnode pdocument::operator <<( const xml::element& i )
{
	_lib_usecounter = __gp_Xerces_init; // xerces usage counter
	//cout << __FUNCTION__ << ": xerces_use=" << __gp_Xerces_init.use_count() << endl;
	
	DOMImplementation* impl =  DOMImplementationRegistry::getDOMImplementation(X("LS")); 
	_document_ptr = impl->createDocument(
		0,                  // root element namespace URI.
		X(i.name.c_str()),	// root element name
		0);                 // document type object (DTD). 

	_doc_allocated = true;
	_docid = i.name;

	_node_ptr = _document_ptr;

	DOMElement* rootElem = _document_ptr->getDocumentElement();
	rootElem->setAttribute( X("xmlns:dt"), X("urn:schemas-microsoft-com:datatypes") );
	return rootElem;
}

pnode pdocument::operator >>( const xml::element& i) const
{
	DOMElement* rootElem = _document_ptr->getDocumentElement();

	if(XMLString::equals(rootElem->getNodeName(),X(i.name.c_str())))
		return rootElem;

	throw hc::CException(hc::ex_val("Root element not match to",i.name));
}
/*pnode pdocument::clone( bool deep ) const
{
	return _document_ptr->cloneNode( deep );
}*/
	

bool pdocument::load_xml( const std::string& iFile )
{
	DOMImplementation *impl = DOMImplementationRegistry::getDOMImplementation(X("LS"));
	if(_dom_builder)
		throw hc::CException(hc::ex_val("DOMImplementation failed",std::string()));

	_lib_usecounter = __gp_Xerces_init; 
	_dom_builder = ((DOMImplementationLS*)impl)->createLSParser(DOMImplementationLS::MODE_SYNCHRONOUS, 0);

	if (_dom_builder->getDomConfig()->canSetParameter(XMLUni::fgDOMValidate, true))
		_dom_builder->getDomConfig()->setParameter(XMLUni::fgDOMValidate, true);
    if (_dom_builder->getDomConfig()->canSetParameter(XMLUni::fgXercesSchema, true))
		_dom_builder->getDomConfig()->setParameter(XMLUni::fgXercesSchema, true);
    if (_dom_builder->getDomConfig()->canSetParameter(XMLUni::fgXercesSchemaFullChecking, true))
		_dom_builder->getDomConfig()->setParameter(XMLUni::fgXercesSchemaFullChecking, true);
	
	DOMCountErrorHandler errorHandler;    
	_dom_builder->getDomConfig()->setParameter(XMLUni::fgDOMErrorHandler, &errorHandler);

	try
	{
		_document_ptr = _dom_builder->parseURI(iFile.c_str());
		if (errorHandler.getSawErrors())
		{
		    throw hc::CException(hc::ex_val("Exception",std::string("Error while processing xml")));		    
		}
		else
		{ 
		    std::string doc_name = X2C(_document_ptr->getNodeName());
		    DOMElement* rootElem = _document_ptr->getDocumentElement();
		    std::string root_name = X2C(rootElem->getNodeName());
		    _docid = root_name;
		    _node_ptr = _document_ptr;
		}
	}
    catch (const XMLException& toCatch) 
	{
		/*cout << "Exception message is: \n" << X2C(toCatch.getMessage()) << "\n";*/
		throw hc::CException(hc::ex_val("XMLException",std::string(X2C(toCatch.getMessage()))));
	}
	catch (const DOMException& toCatch) 
	{
		/*cout << "Exception message is: \n" << X2C(toCatch.msg) << "\n";*/
		throw hc::CException(hc::ex_val("DOMException",std::string(X2C(toCatch.msg))));
	}
	catch (...) 
	{
		/*cout << "Unexpected Exception \n" ;*/
		throw hc::CException(hc::ex_val("Exception", errorHandler.getErrorLog()  ));
	}
	
	/*parser->release();	
	delete inp_src;
	delete in_buf; */
	return true;
}


std::string pdocument::get_xml() const
{
	DOMImplementation* impl = DOMImplementationRegistry::getDOMImplementation(X("LS"));

	DOMLSSerializer* theSerializer = ((DOMImplementationLS*)impl)->createLSSerializer();
    DOMLSOutput* theOutputDesc = ((DOMImplementationLS*)impl)->createLSOutput();
    
	DOMConfiguration* theDC = theSerializer->getDomConfig();
	theOutputDesc->setEncoding(X("UTF-8"));
	
	XMLFormatTarget* memTarget = new MemBufFormatTarget();
    theOutputDesc->setByteStream(memTarget);

	
	DOMCountErrorHandler errorHandler;    
	theSerializer->getDomConfig()->setParameter(XMLUni::fgDOMErrorHandler, &errorHandler);
	string strFeedback;
  	try 
	{
		DOMElement *rootElem = _document_ptr->getDocumentElement();
		strFeedback = X2C( theSerializer->writeToString(rootElem) ); // write(rootElem, theOutputDesc);
	}
    catch (const XMLException& toCatch) 
	{
		/*cout << "Exception message is: \n" << X2C(toCatch.getMessage()) << "\n";*/
		throw hc::CException(hc::ex_val("XMLException",std::string(X2C(toCatch.getMessage()))));
	}
	catch (const DOMException& toCatch) 
	{
		/*cout << "Exception message is: \n" << X2C(toCatch.msg) << "\n";*/
		throw hc::CException(hc::ex_val("DOMException",std::string(X2C(toCatch.msg))));
	}
	catch (...) 
	{
		/*cout << "Unexpected Exception \n" ;*/
		throw hc::CException(hc::ex_val("Exception", errorHandler.getErrorLog()  ));
	}

	//const unsigned char* _t1_ref = ((MemBufFormatTarget*)memTarget)->getRawBuffer();
	//int _t1_len = (int)((MemBufFormatTarget*)memTarget)->getLen();
	//std::string s1( (const char*)_t1_ref, _t1_len );
	
	theSerializer->release();
	theOutputDesc->release();
	
	return strFeedback;
}

pnode pdocument::get_root()
{
	DOMElement* rootElem = _document_ptr->getDocumentElement();
	rootElem->setAttribute( X("xmlns:dt"), X("urn:schemas-microsoft-com:datatypes") );
	return rootElem;
}

DOMCountErrorHandler::DOMCountErrorHandler() :    fSawErrors(false), errorLog("")
{}

DOMCountErrorHandler::~DOMCountErrorHandler()
{}
// ---------------------------------------------------------------------------
//  DOMCountHandlers: Overrides of the DOM ErrorHandler interface
// ---------------------------------------------------------------------------
bool DOMCountErrorHandler::handleError(const DOMError& domError)
{
    if ( domError.getSeverity() == DOMError::DOM_SEVERITY_FATAL_ERROR )
    {
		fSawErrors = true;
		errorLog = "\nFatal Error at file " + std::string(X2C(domError.getLocation()->getURI() ));
		errorLog = errorLog  + ", line ";
		errorLog = errorLog  + hc::as_string<int>(domError.getLocation()->getLineNumber());
		errorLog = errorLog  + ", char ";
		errorLog = errorLog  + hc::as_string<int>(domError.getLocation()->getColumnNumber());
		/*errorLog = errorLog  + ", where ";
		errorLog = errorLog  + string(X2C(domError.getLocation()->getErrorNode()->getNodeName())); 
		errorLog = errorLog  + ", what ";
		errorLog = errorLog  + string(X2C(domError.getLocation()->getErrorNode()->getNodeValue())); 
		errorLog = errorLog  + ", uri ";
		errorLog = errorLog  + string(X2C(domError.getLocation()->getURI() ));*/ 
		errorLog = errorLog  + "\n  Message: ";
		errorLog = errorLog  + std::string(X2C(domError.getMessage()));
		errorLog = errorLog  + "\n";
		return true;
    }
    return true;
}
                      
void DOMCountErrorHandler::resetErrors()
{
    fSawErrors = false;
}

std::string DOMCountErrorHandler::getErrorLog()
{
    return errorLog;
}
                          



